package com.ticket.sass.provider.business.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ticket.sass.common.entity.provider.TenantEntity;
import com.ticket.sass.common.entity.tenant.CinemaEntity;
import com.ticket.sass.common.entity.tenant.CinemaExtendEntity;
import com.ticket.sass.common.entity.tenant.ServiceChargeEntity;
import com.ticket.sass.common.entity.tenant.TicketServerConfigEntity;
import com.ticket.sass.common.exception.enums.ErrorCode;
import com.ticket.sass.common.exception.exception.BadRequestException;
import com.ticket.sass.provider.business.CinemaBusiness;
import com.ticket.sass.provider.config.AppConfig;
import com.ticket.sass.provider.dto.input.cinema.CinemaAddInput;
import com.ticket.sass.provider.dto.input.cinema.CinemaListInput;
import com.ticket.sass.provider.dto.input.cinema.CinemaUpdInput;
import com.ticket.sass.provider.dto.input.cinema.TicketServerConfigInput;
import com.ticket.sass.provider.dto.output.cinema.CinemaListOutput;
import com.ticket.sass.provider.dto.output.cinema.ServiceChargeOutput;
import com.ticket.sass.provider.dto.output.cinema.TicketServerConfigOutput;
import com.ticket.sass.provider.service.LabModel;
import com.ticket.sass.provider.service.PageModel;
import com.ticket.sass.provider.service.impl.*;
import com.ticket.sass.provider.util.EscapeUtil;
import com.ticket.sass.provider.util.FileUtil;
import com.ticket.sass.provider.util.GsonUtil;
import com.ticket.sass.provider.util.ModelUtil;
import lombok.AllArgsConstructor;
import org.modelmapper.TypeToken;
import org.postgresql.geometric.PGpoint;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author ywb
 * @date 2024-03-15 15:45
 */
@Service
@AllArgsConstructor
public class CinemaBusinessImpl implements CinemaBusiness {
    final FileUtil fileUtil;
    final ModelUtil modelUtil;
    final AppConfig appConfig;
    final CinemaServiceImpl service;
    final AppServiceImpl appService;
    final AreaServiceImpl areaService;
    final TenantServiceImpl tenantService;
    final AppCinemaMapServiceImpl appCinemaMapService;
    final CinemaExtendServiceImpl cinemaExtendService;
    final ServiceChargeServiceImpl serviceChargeService;
    final TicketServerConfigServiceImpl ticketServerConfigService;
    
    @Override
    public PageModel<CinemaListOutput> list(CinemaListInput input) {
        IPage<CinemaEntity> page = service.iPage(input);
        List<CinemaListOutput> outputs = modelUtil.listToList(page.getRecords(), new TypeToken<List<CinemaListOutput>>(){}.getType());
        
        // 聚合数据
        List<Long> cinemaIds = outputs.stream().map(CinemaListOutput::getId).collect(Collectors.toList());
        List<Long> tenantIds = outputs.stream().map(CinemaListOutput::getTenantId).collect(Collectors.toList());
        List<String> areaCodes = outputs.stream().map(CinemaListOutput::getAreaCode).collect(Collectors.toList());
        Map<Long, TicketServerConfigEntity> ticketServerConfigMap = ticketServerConfigService.getTicketServerConfigMapByCinemaIds(cinemaIds);
        Map<Long, TenantEntity> tenantMap = tenantService.mapByIds(tenantIds);
        Map<Long, CinemaExtendEntity> cinemaExtendMap = cinemaExtendService.getCinemaExtendMapByCinemaId(cinemaIds);
        Map<String, String> areaMergerNameMap = areaService.getMergerNamesByCodes(areaCodes);
        Map<Long, ServiceChargeEntity> serviceChargeMap = serviceChargeService.getServiceChargesByCinemaIds(cinemaIds);
        
        // 汇总数据
        outputs.forEach(output -> {
            output.setTicketServerConfig(new TicketServerConfigOutput(ticketServerConfigMap.get(output.getId())));
            
            CinemaExtendEntity cinemaExtendEntity = cinemaExtendMap.get(output.getId());
            output.setContact(Arrays.asList(getCinemaContact(cinemaExtendEntity)));
            
            TenantEntity tenant = tenantMap.get(output.getTenantId());
            if (Objects.nonNull(tenant)){
                output.setTenant(new LabModel(tenant.getId(), tenant.getName()));
            }
            output.setArea(areaMergerNameMap.getOrDefault(output.getAreaCode(), ""));
            output.setServiceChargeConfig(ServiceChargeOutput.toOutput(serviceChargeMap.get(output.getId())));
        });
        return new PageModel<>(page.getTotal(), outputs);
    }

    private String[] getCinemaContact(CinemaExtendEntity entity) {
        if (entity == null) {
            return new String[0];
        }
        
        if (StrUtil.isEmpty(entity.getContact())) {
            return new String[0];
        }
        return entity.getContact().split(",");
    }
    
    @Override
    public void add(CinemaAddInput input) {
        validateTenantId(input.getTenantId());
        if (service.count(new QueryWrapper<CinemaEntity>().eq("tenant_id", input.getTenantId()).eq("zz_code", input.getZzCode())) > 0){
            throw new BadRequestException(
                ErrorCode.RECORD_EXIST,
                EscapeUtil.errorMessage("zzCode", "影院编码已存在")
            );
        }
        // 数据处理
        fileUtil.tempFieldPro(input, "logo");
        CinemaEntity cinemaEntity = modelUtil.mapToMap(input, CinemaEntity.class);

        try {
            PGpoint pGpoint = new PGpoint(cinemaEntity.getLng() + "," + cinemaEntity.getLat());
            cinemaEntity.setPoint(pGpoint);
        } catch (Exception ignored){
        
        }
        
        service.save(cinemaEntity);
        
        if (CollectionUtil.isNotEmpty(input.getContact())){
            CinemaExtendEntity cinemaExtends = new CinemaExtendEntity(cinemaEntity.getId(), String.join(",", input.getContact()));
            cinemaExtends.setTenantId(input.getTenantId());
            cinemaExtendService.save(cinemaExtends);
        }
        
        TicketServerConfigInput config = input.getTicketServerConfig();
        TicketServerConfigEntity ticketServerConfigEntity = new TicketServerConfigEntity(
            config.getServerUrl(),
            config.getPlatform(),
            GsonUtil.toJsonString(config.getData()),
            cinemaEntity.getId(),
            cinemaEntity.getTenantId()
        );
        
        ticketServerConfigService.save(ticketServerConfigEntity);
        
        serviceChargeService.save(new ServiceChargeEntity(input.getServiceChargeConfig().getChannelServiceFee(), cinemaEntity.getId(), cinemaEntity.getTenantId()));
    }
    
    
    @Override
    public void upd(CinemaUpdInput input) {
        validateId(input.getId());
        CinemaEntity cinema = service.getById(input.getId());
        
        
        if (service.count(new QueryWrapper<CinemaEntity>().eq("tenant_id", cinema.getTenantId()).eq("zz_code", input.getZzCode()).ne("id", input.getId())) > 0){
            throw new BadRequestException(
                ErrorCode.RECORD_EXIST,
                EscapeUtil.errorMessage("zzCode", "影院编码已存在")
            );
        }
        fileUtil.tempFieldPro(input, "logo");
        
        CinemaEntity cinemaEntity = modelUtil.mapToMap(input, CinemaEntity.class);

        try {
            PGpoint pGpoint = new PGpoint(cinemaEntity.getLng() + "," + cinemaEntity.getLat());
            cinemaEntity.setPoint(pGpoint);
        } catch (Exception ignore){
        
        }
        service.updateById(cinemaEntity);
        
        cinemaExtendService.updateContactByCinemaId(input.getId(), String.join(",", input.getContact()), cinema.getTenantId());
        
        TicketServerConfigInput config = input.getTicketServerConfig();
        // 创建 TicketServerConfigEntity 对象
        TicketServerConfigEntity ticketServerConfigEntity = new TicketServerConfigEntity(
            config.getServerUrl(),
            config.getPlatform(),
            GsonUtil.toJsonString(config.getData()),
            cinema.getId(),
            cinemaEntity.getTenantId()
        );
     
        ticketServerConfigService.updateByCinemaId(cinema.getId(), ticketServerConfigEntity);
        
        serviceChargeService.updateChannelServiceFeeByCinemaId(input.getId(), input.getServiceChargeConfig().getChannelServiceFee());
    }
    
    private void validateId(Long id) {
        if (service.isEmpty(id)) {
            throw new BadRequestException(
                ErrorCode.RECORD_NOT_EXIST,
                EscapeUtil.errorMessage("id", "记录不存在")
            );
        }
    }
    
    private void validateTenantId(Long tenantId) {
        if (tenantService.isEmpty(tenantId)) {
            throw new BadRequestException(
                ErrorCode.RECORD_NOT_EXIST,
                EscapeUtil.errorMessage("tenantId", "租户不存在")
            );
        }
    }
}
